package fr.utbm.gi.vi51.project.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.net.URL;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
import javax.vecmath.Point2d;
import javax.vecmath.Vector2d;

import org.arakhne.vmutil.Resources;
import org.arakhne.vmutil.locale.Locale;
import org.janusproject.kernel.agent.Kernels;

import fr.utbm.gi.vi51.framework.FrameworkLauncher;
import fr.utbm.gi.vi51.framework.environment.EnvironmentEvent;
import fr.utbm.gi.vi51.framework.environment.SituatedObject;
import fr.utbm.gi.vi51.framework.gui.FrameworkGUI;
import fr.utbm.gi.vi51.framework.util.GeometryUtil;
import fr.utbm.gi.vi51.project.GlobalSettings;
import fr.utbm.gi.vi51.project.MainProgram;
import fr.utbm.gi.vi51.project.agent.Enemy;
import fr.utbm.gi.vi51.project.agent.EnemyMarine;
import fr.utbm.gi.vi51.project.agent.Marine;
import fr.utbm.gi.vi51.project.agent.Mutalisk;
import fr.utbm.gi.vi51.project.agent.Zergling;
import fr.utbm.gi.vi51.project.agent.body.ProjectileBody;
import fr.utbm.gi.vi51.project.agent.body.UnitBody;
import fr.utbm.gi.vi51.project.environment.EnvironmentObject;
import fr.utbm.gi.vi51.project.environment.EnvironmentType;
import fr.utbm.gi.vi51.project.environment.WorldModel;
import fr.utbm.gi.vi51.project.environment.WorldModelEvent;
import fr.utbm.gi.vi51.project.environment.WorldModelState;
import fr.utbm.gi.vi51.project.environment.WorldModelStateProvider;
import fr.utbm.gi.vi51.project.formations.DeltaFormation;
import fr.utbm.gi.vi51.project.formations.FormationBody;
import fr.utbm.gi.vi51.project.formations.FormationOrientation;
import fr.utbm.gi.vi51.project.formations.FormationSlot;
import fr.utbm.gi.vi51.project.formations.LineFormation;
import fr.utbm.gi.vi51.project.formations.SplitFormation;
import fr.utbm.gi.vi51.project.formations.SpreadFormation;
import fr.utbm.gi.vi51.project.formations.SquareFormation;

public class GUI extends JFrame implements FrameworkGUI {

	private static final long serialVersionUID = -2393638827023549444L;

	// Agent Radiuses
	private static final double SPOT_RADIUS = 1.;

	// Icons
	static final int ICON_WIDTH;
	static final int ICON_HEIGHT;
	static ImageIcon BACKGROUND;

	// HUD
	static boolean showFormation = false;
	static boolean showLifeBar = true;
	static final SavedHUDButtons collectionbutton = new SavedHUDButtons();
	ButtonType pressedButton = null;

	// World
	private final World world;
	WorldModelState lastState = null;
	private WorldModelStateProvider environment = null;

	// Draw icon on drag
	int mousePositionX = 0;
	int mousePositionY = 0;

	// ??
	Rectangle rect;

	static {
		URL url_background = Resources.getResource(GUI.class, "background.png"); //$NON-NLS-1$
		assert (url_background != null);
		BACKGROUND = new ImageIcon(url_background);

		ICON_WIDTH = 21;
		ICON_HEIGHT = 26;
	}

	public GUI(double worldWidth, double worldHeight) {
		setTitle(Locale.getString(MainProgram.class, "Team of Marines")); //$NON-NLS-1$

		Container content = getContentPane();
		content.setLayout(new BorderLayout());

		this.world = new World();
		this.world.setPreferredSize(new Dimension((int) worldWidth, (int) worldHeight));

		this.rect = new Rectangle(0, 0, (int) worldWidth, (int) worldHeight);

		JScrollPane scroll = new JScrollPane(this.world);
		content.add(BorderLayout.CENTER, scroll);

		// Detect mouse and set it as target location
		this.world.addMouseMotionListener(new MouseMotionListener() {
			@Override
			public void mouseDragged(MouseEvent e) {
				GUI.this.mousePositionX = e.getX();
				GUI.this.mousePositionY = e.getY();
				repaint();
			}

			@Override
			public void mouseMoved(MouseEvent e) {
				repaint();
			}
		});

		this.world.addMouseListener(new MouseListener() {

			@Override
			public void mousePressed(MouseEvent event) {
				if (event.getX() > GlobalSettings.WORLD_SIZE_X - GlobalSettings.MENU_SIZE_X) {
					for (Button button : GUI.collectionbutton.getObjects()) {
						if (event.getX() > button.getX() && event.getX() < button.getX() + button.getWidth()
								&& event.getY() > button.getY() && event.getY() < button.getY() + button.getHeight()) {
							switch (button.getType()) {
							case DISPLAYFORMATION:
								showFormation = !showFormation;
								break;
							case DISPLAYLIFEBAR:
								showLifeBar = !showLifeBar;
								break;
							case DELTA:
								FormationBody deltaBody = new DeltaFormation(FormationOrientation.EAST);
								deltaBody.scale(WorldModel.getMarines().size());
								Marine.formationBody = deltaBody;
								break;
							case LINE:
								FormationBody lineBody = new LineFormation(FormationOrientation.EAST);
								lineBody.scale(WorldModel.getMarines().size());
								Marine.formationBody = lineBody;
								break;
							case SPREAD:
								FormationBody spreadBody = new SpreadFormation(FormationOrientation.EAST);
								spreadBody.scale(WorldModel.getMarines().size());
								Marine.formationBody = spreadBody;
								break;
							case SPLIT:
								new SplitFormationDialog().setVisible(true);
								break;
							case AUTO:
								ArrayList<FormationBody> subFormations1 = new ArrayList<>();
								FormationBody subformation11 = new LineFormation(FormationOrientation.SOUTH);
								FormationBody subformation13 = new LineFormation(FormationOrientation.EAST);

								FormationBody subformation21 = new LineFormation(FormationOrientation.EAST);
								FormationBody subformation22 = new SpreadFormation(FormationOrientation.WEST);
								ArrayList<FormationBody> subFormations2 = new ArrayList<>();
								subFormations2.add(subformation21);
								subFormations2.add(subformation22);
								FormationBody subformation12 = new SplitFormation(FormationOrientation.NORTH,
										subFormations2);

								subFormations1.add(subformation11);
								subFormations1.add(subformation12);
								subFormations1.add(subformation13);

								FormationBody formation = new SplitFormation(FormationOrientation.EAST, subFormations1);
								formation.scale(WorldModel.getMarines().size());
								Marine.formationBody = formation;
								break;
							case SQUARE:
								FormationBody squareBody = new SquareFormation(FormationOrientation.EAST);
								squareBody.scale(WorldModel.getMarines().size());
								Marine.formationBody = squareBody;
								break;
							case PLAY:
								Kernels.get().resume();
								break;
							case PAUSE:
								Kernels.get().pause();
								break;
							case INFO:
								JOptionPane
										.showConfirmDialog(
												null,
												Messages.getString("GUI.Title"), Messages.getString("GUI.Text"), JOptionPane.DEFAULT_OPTION); //$NON-NLS-1$ //$NON-NLS-2$
								break;
							case QUIT:
								FrameworkLauncher.stopSimulation();
								break;
							default:
								GUI.this.pressedButton = button.getType();
								break;
							}
							return;
						}
					}
					GUI.this.pressedButton = null;
				} else if (!event.isMetaDown()) {
					for (SituatedObject so : GUI.this.lastState.getObjects()) {
						if (so instanceof EnvironmentObject && event.getX() > (so.getX() - so.getSize())
								&& event.getX() < (so.getX() + so.getSize())
								&& event.getY() > (so.getY() - so.getSize())
								&& event.getY() < (so.getY() + so.getSize())) {
							FrameworkLauncher.deleteEnvironmentObject((EnvironmentObject) so);
						}
					}
				}
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				if (e.isMetaDown()) {
					FrameworkLauncher.deleteEnvironmentObject(WorldModel.getTarget());
					WorldModel.setTarget(AddEnvironmentObj(ButtonType.TARGET, e.getX(), e.getY()));
					FrameworkLauncher.launchEnvironmentObject(WorldModel.getTarget());
				} else if (GUI.this.pressedButton != null) {
					if (GUI.this.pressedButton == ButtonType.ENEMY) {
						Enemy enemy = new EnemyMarine();
						FrameworkLauncher.launchAgent(enemy, e.getX(), e.getY());
						Kernels.get().launchLightAgent(enemy);
					} else if (GUI.this.pressedButton == ButtonType.ZERGLING) {
						Enemy enemy1 = new Zergling();
						Enemy enemy2 = new Zergling();
						FrameworkLauncher.launchAgent(new Zergling(), e.getX() - 1, e.getY());
						FrameworkLauncher.launchAgent(new Zergling(), e.getX() + 1, e.getY());
						Kernels.get().launchLightAgent(enemy1);
						Kernels.get().launchLightAgent(enemy2);
					} else if (GUI.this.pressedButton == ButtonType.MUTALISK) {
						Enemy enemy3 = new Mutalisk();
						FrameworkLauncher.launchAgent(enemy3, e.getX(), e.getY());
						Kernels.get().launchLightAgent(enemy3);
					} else if (e.getX() < GlobalSettings.WORLD_SIZE_X - GlobalSettings.MENU_SIZE_X) {
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, e.getX(), e
								.getY()));
					}
					GUI.this.pressedButton = null;
				}

			}

			@Override
			public void mouseEntered(MouseEvent e) {
				// Do nothing
			}

			@Override
			public void mouseExited(MouseEvent e) {
				// Do nothing
			}

			@Override
			public void mouseClicked(MouseEvent event) {
				// Do nothing
			}

		});

		/*
		 * Please don't spam create units. If you want to create a lot of units, pause the Janus Kernel first or it
		 * might throw a ConcurrentModificationException
		 */
		this.world.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
				// Do nothing
			}

			@Override
			public void keyPressed(KeyEvent event) {
				Point mouse = MouseInfo.getPointerInfo().getLocation();
				if (event.getKeyCode() == KeyEvent.VK_A) {
					GUI.this.mousePositionX = (int) mouse.getX() - 2;
					GUI.this.mousePositionY = (int) mouse.getY() - 24;
					GUI.this.pressedButton = ButtonType.ENEMY;
				} else if (event.getKeyCode() == KeyEvent.VK_Z) {
					GUI.this.mousePositionX = (int) mouse.getX() + 0;
					GUI.this.mousePositionY = (int) mouse.getY() - 24;
					GUI.this.pressedButton = ButtonType.ZERGLING;
				} else if (event.getKeyCode() == KeyEvent.VK_E) {
					GUI.this.mousePositionX = (int) mouse.getX() + 1;
					GUI.this.mousePositionY = (int) mouse.getY() - 25;
					GUI.this.pressedButton = ButtonType.MUTALISK;
				} else if (event.getKeyCode() == KeyEvent.VK_W) {
					GUI.this.mousePositionX = (int) mouse.getX() + 1;
					GUI.this.mousePositionY = (int) mouse.getY() - 25;
					GUI.this.pressedButton = ButtonType.TREE;
				} else if (event.getKeyCode() == KeyEvent.VK_X) {
					GUI.this.mousePositionX = (int) mouse.getX() + 0;
					GUI.this.mousePositionY = (int) mouse.getY() - 19;
					GUI.this.pressedButton = ButtonType.CAVE;
				} else if (event.getKeyCode() == KeyEvent.VK_C) {
					GUI.this.mousePositionX = (int) mouse.getX() + 6;
					GUI.this.mousePositionY = (int) mouse.getY() - 20;
					GUI.this.pressedButton = ButtonType.COLUMN;
				} else if (event.getKeyCode() == KeyEvent.VK_V) {
					GUI.this.mousePositionX = (int) mouse.getX() + 1;
					GUI.this.mousePositionY = (int) mouse.getY() - 23;
					GUI.this.pressedButton = ButtonType.MOUNTAIN;
				} else if (event.getKeyCode() == KeyEvent.VK_B) {
					GUI.this.mousePositionX = (int) mouse.getX() + 1;
					GUI.this.mousePositionY = (int) mouse.getY() - 25;
					GUI.this.pressedButton = ButtonType.BUILDING;
				} else if (event.getKeyCode() == KeyEvent.VK_N) {
					GUI.this.mousePositionX = (int) mouse.getX() - 4;
					GUI.this.mousePositionY = (int) mouse.getY() - 25;
					GUI.this.pressedButton = ButtonType.LAKE;
				} else if (event.getKeyCode() == KeyEvent.VK_Q) {
					GUI.this.pressedButton = ButtonType.SQUARE;
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
				} else if (event.getKeyCode() == KeyEvent.VK_S) {
					GUI.this.pressedButton = ButtonType.DELTA;
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
				} else if (event.getKeyCode() == KeyEvent.VK_D) {
					GUI.this.pressedButton = ButtonType.LINE;
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
				} else if (event.getKeyCode() == KeyEvent.VK_F) {
					GUI.this.pressedButton = ButtonType.SPREAD;
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
				} else if (event.getKeyCode() == KeyEvent.VK_G) {
					GUI.this.pressedButton = ButtonType.SPLIT;
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
				} else if (event.getKeyCode() == KeyEvent.VK_SPACE) {
					GUI.this.mousePositionX = -100;
					GUI.this.mousePositionY = -100;
					if (Kernels.get().isPaused()) {
						GUI.this.pressedButton = ButtonType.PLAY;
					} else {
						GUI.this.pressedButton = ButtonType.PAUSE;
					}
				}
			}

			@Override
			public void keyReleased(KeyEvent event) {
				Point mouse = MouseInfo.getPointerInfo().getLocation();
				if (GUI.this.pressedButton != null
						&& mouse.getX() < GlobalSettings.WORLD_SIZE_X - GlobalSettings.MENU_SIZE_X) {
					switch (GUI.this.pressedButton) {
					case ENEMY:
						Enemy enemy = new EnemyMarine();
						FrameworkLauncher.launchAgent(enemy, mouse.getX() - 7, mouse.getY() - 28);
						Kernels.get().launchLightAgent(enemy);
						break;
					case ZERGLING:
						Enemy enemy1 = new Zergling();
						Enemy enemy2 = new Zergling();
						FrameworkLauncher.launchAgent(enemy1, mouse.getX() - 7, mouse.getY() - 30);
						FrameworkLauncher.launchAgent(enemy2, mouse.getX() - 1, mouse.getY() - 30);
						Kernels.get().launchLightAgent(enemy1);
						Kernels.get().launchLightAgent(enemy2);
						break;
					case MUTALISK:
						Enemy enemy3 = new Mutalisk();
						FrameworkLauncher.launchAgent(enemy3, mouse.getX() - 5, mouse.getY() - 28);
						Kernels.get().launchLightAgent(enemy3);
						break;
					case MOUNTAIN:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX() + 1, (int) mouse.getY() - 23));
						break;
					case TREE:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX() + 1, (int) mouse.getY() - 25));
						break;
					case CAVE:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX(), (int) mouse.getY() - 19));
						break;
					case COLUMN:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX() + 6, (int) mouse.getY() - 20));
						break;
					case BUILDING:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX() + 1, (int) mouse.getY() - 25));
						break;
					case LAKE:
						FrameworkLauncher.launchEnvironmentObject(AddEnvironmentObj(GUI.this.pressedButton, (int) mouse
								.getX() - 4, (int) mouse.getY() - 25));
						break;
					case SQUARE:
						FormationBody squareBody = new SquareFormation(FormationOrientation.EAST);
						squareBody.scale(WorldModel.getMarines().size());
						Marine.formationBody = squareBody;
						break;
					case DELTA:
						FormationBody deltaBody = new DeltaFormation(FormationOrientation.EAST);
						deltaBody.scale(WorldModel.getMarines().size());
						Marine.formationBody = deltaBody;
						break;
					case LINE:
						FormationBody lineBody = new LineFormation(FormationOrientation.EAST);
						lineBody.scale(WorldModel.getMarines().size());
						Marine.formationBody = lineBody;
						break;
					case SPLIT:
						new SplitFormationDialog().setVisible(true);
						break;
					case SPREAD:
						FormationBody spreadBody = new SpreadFormation(FormationOrientation.EAST);
						spreadBody.scale(WorldModel.getMarines().size());
						Marine.formationBody = spreadBody;
						break;
					case PLAY:
						Kernels.get().resume();
						break;
					case PAUSE:
						Kernels.get().pause();
						break;
					default:
						break;
					}

					GUI.this.pressedButton = null;
				}
			}

		});

		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		this.world.setFocusable(true);
		pack();

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void environmentChanged(EnvironmentEvent event) {
		synchronized (getTreeLock()) {
			if (event instanceof WorldModelEvent && this.environment == null) {
				WorldModelEvent e = (WorldModelEvent) event;
				this.environment = e.getStateProvider();
			}
			this.lastState = this.environment.getState();
			repaint();
		}
	}

	/**
	 * Replies the last environment state.
	 * 
	 * @return the last environment state.
	 */
	protected WorldModelState getLastState() {
		return this.lastState;
	}

	protected static EnvironmentObject AddEnvironmentObj(ButtonType type, int x, int y) {
		switch (type) {
		case MOUNTAIN:
			return new EnvironmentObject(32, x, y, EnvironmentType.MOUNTAIN, 32, 32);
		case TREE:
			return new EnvironmentObject(32, x, y, EnvironmentType.TREE, 32, 32);
		case BUILDING:
			return new EnvironmentObject(32, x, y, EnvironmentType.BUILDING, 32, 32);
		case CAVE:
			return new EnvironmentObject(32, x, y, EnvironmentType.CAVE, 32, 32);
		case COLUMN:
			return new EnvironmentObject(32, x, y, EnvironmentType.COLUMN, 32, 32);
		case LAKE:
			return new EnvironmentObject(32, x, y, EnvironmentType.LAKE, 16, 16);
		case TARGET:
			return new EnvironmentObject(48, x, y, EnvironmentType.TARGET, 48, 48);
		default:
			break;
		}
		return null;
	}

	/**
	 * 
	 *
	 */
	private class World extends JPanel {

		private static final long serialVersionUID = -660114247027180145L;
		private ImageIcon objet_ICON;

		public World() {
			// Do nothing
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			Graphics2D g2d = (Graphics2D) g;

			// World
			BACKGROUND.paintIcon(this, g2d, 0, 0);

			// HUD
			g2d.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 15)); //$NON-NLS-1$
			g2d.drawString("Enviroment", 1190, 20); //$NON-NLS-1$
			g2d.drawString("Enemy", 1200, 210); //$NON-NLS-1$
			g2d.drawString("Formation", 1200, 310);//$NON-NLS-1$
			g2d.drawString("HUD", 1215, 540);//$NON-NLS-1$
			g2d.drawString("A", 1180, 250);//$NON-NLS-1$
			g2d.drawString("Z", 1210, 250);//$NON-NLS-1$
			g2d.drawString("E", 1265, 270);//$NON-NLS-1$
			g2d.drawString("W", 1205, 70);//$NON-NLS-1$
			g2d.drawString("X", 1255, 70);//$NON-NLS-1$
			g2d.drawString("C", 1205, 117);//$NON-NLS-1$
			g2d.drawString("V", 1255, 117);//$NON-NLS-1$
			g2d.drawString("B", 1205, 162);//$NON-NLS-1$
			g2d.drawString("N", 1255, 162);//$NON-NLS-1$
			g2d.drawString("Q", 1207, 370);//$NON-NLS-1$
			g2d.drawString("S", 1260, 370);//$NON-NLS-1$
			g2d.drawString("D", 1205, 415);//$NON-NLS-1$
			g2d.drawString("F", 1265, 430);//$NON-NLS-1$
			g2d.drawString("G", 1250, 470);//$NON-NLS-1$
			g2d.drawString("SPACE", 1200, 650);//$NON-NLS-1$

			drawButtons(g2d);

			// Formation
			if (showFormation) {
				drawFormations(g2d, Marine.formationBody);
			}

			// Agents and Environment
			drawEnviromentObjects(g2d);

			// Draw on drag to help user position the selected object
			if (GUI.this.pressedButton != null
					&& GUI.this.mousePositionX < GlobalSettings.WORLD_SIZE_X - GlobalSettings.MENU_SIZE_X - 20) {
				drawObject(g2d, GUI.this.mousePositionX - 16, GUI.this.mousePositionY - 16, GUI.this.pressedButton);
			}

		}

		private void drawEnviromentObjects(Graphics2D g2d) {
			WorldModelState state = getLastState();
			if (state != null) {
				for (SituatedObject object : state.getObjects()) {
					if (object instanceof UnitBody) {
						drawAgent(g2d, (int) object.getX(), (int) object.getY(), (UnitBody) object);
						if (showLifeBar) {
							drawLifeBar(g2d, (UnitBody) object);
						}
					} else if (object instanceof ProjectileBody) {
						drawAgent(g2d, (int) object.getX(), (int) object.getY(), (ProjectileBody) object);
					} else if (object instanceof EnvironmentObject) {
						if (((EnvironmentObject) object).getType() == EnvironmentType.TARGET) {
							drawObject(g2d, (int) object.getX() - 24, (int) object.getY() - 24,
									((EnvironmentObject) object).getType());
						} else {
							drawObject(g2d, (int) object.getX() - 16, (int) object.getY() - 16,
									((EnvironmentObject) object).getType());
						}
					}
				}
			}
		}

		private void drawButtons(Graphics2D g2d) {
			for (Button p : GUI.collectionbutton.getObjects()) {
				drawObject(g2d, p.getX(), p.getY(), p.getType());
			}
		}

		private void drawAgent(Graphics2D g2d, int x, int y, UnitBody unitBody) {
			unitBody.getCurrentIcon().paintIcon(this, g2d, x - ICON_WIDTH / 2, y - ICON_HEIGHT / 2);
		}

		private void drawAgent(Graphics2D g2d, int x, int y, ProjectileBody projectileBody) {
			projectileBody.getCurrentIcon().paintIcon(this, g2d, x - ICON_WIDTH / 2, y - ICON_HEIGHT / 2);
		}

		/*
		 * This lifeBar has some position problems because the Graphics2D.fillRect() method only take integers as
		 * parameters. It was left like that because it isn't a core problem. Its only purpose is balance testing.
		 */
		private void drawLifeBar(Graphics2D g2d, UnitBody body) {
			int percent = body.getHealth() <= 0 ? 0 : body.getHealth() * 100 / body.getMaxHealth();
			int greenSize = percent * 20 / 100;
			g2d.setColor(new Color(0, 255, 0));
			g2d.fillRect((int) body.getPosition().getX() - (20 - greenSize) / 2 - 10,
					(int) body.getPosition().getY() - 15, greenSize, 2);
			g2d.setColor(new Color(255, 0, 0));
			g2d.fillRect((int) body.getPosition().getX() + greenSize / 2 - 10, (int) body.getPosition().getY() - 15,
					20 - greenSize, 2);
		}

		public void drawObject(Graphics2D g2d, int x, int y, ButtonType type) {
			if (type != null) {
				URL url_objet = Resources.getResource(GUI.class, type.iconName);
				this.objet_ICON = new ImageIcon(url_objet);
				this.objet_ICON.paintIcon(this, g2d, x, y);
			}
		}

		private void drawObject(Graphics2D g2d, int x, int y, EnvironmentType type) {
			if (type != null) {
				URL url_objet = Resources.getResource(GUI.class, type.iconName);
				this.objet_ICON = new ImageIcon(url_objet);
				this.objet_ICON.paintIcon(this, g2d, x, y);
			}
		}

		private void drawFormations(Graphics2D g2d, FormationBody bodies) {
			Point2d pos, ppos;
			Vector2d orient;
			int l = (int) (2. * SPOT_RADIUS);
			FormationSlot parent;
			for (FormationSlot spot : bodies.getSlots()) {
				pos = spot.getGlobalPosition();
				orient = GeometryUtil.toOrientationVector(spot.getGlobalOrientation());
				orient.normalize();
				orient.scale(SPOT_RADIUS);
				Color C = new Color(0, 0, 0, 255);
				g2d.setColor(C);
				g2d.fillOval((int) (pos.x - 3), (int) (pos.y - 3), 7, 7);
				g2d.drawOval((int) (pos.x - SPOT_RADIUS), (int) (pos.y - SPOT_RADIUS), l, l);
				g2d.drawString(Integer.toString(spot.getIndex()), (float) pos.x + 5, (float) pos.y);
				g2d.drawLine((int) pos.x, (int) pos.y, (int) (pos.x + orient.x), (int) (pos.y + orient.y));
				parent = spot.getParent();
				if (parent != null) {
					ppos = parent.getGlobalPosition();
					g2d.drawLine((int) pos.x, (int) pos.y, (int) ppos.x, (int) ppos.y);
				}
			}
		}

	}

}